import InlineToggleButton from 'paraviewweb/src/React/Widgets/InlineToggleButtonWidget';
import React from 'react';
import PropTypes from 'prop-types';

import style from 'LightVizStyle/TimePanel.mcss';

import {
  updateTime,
  playTime,
  stopTime,
  addTimeListener,
  removeTimeListener,
} from '../../client';

const VCR_CONTROL = [
  {
    icon: style.goToBeginningButton,
    delta: -1000000,
  },
  {
    icon: style.stepBackButton,
    delta: -1,
  },
  {
    icon: style.playButton,
    action: 'play',
  },
  {
    icon: style.stopButton,
    action: 'stop',
  },
  {
    icon: style.stepForwardButton,
    delta: +1,
  },
  {
    icon: style.goToEndButton,
    delta: +10000000,
  },
];

export default class TimePanel extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      timeIdx: 0,
    };

    this.setTimeIdx = this.setTimeIdx.bind(this);
    this.sliderTimeUpdate = this.sliderTimeUpdate.bind(this);
    this.updateVCR = this.updateVCR.bind(this);
    this.play = this.play.bind(this);
    this.stop = this.stop.bind(this);
  }

  componentWillMount() {
    this.callbackId = addTimeListener((timeIdx) => {
      this.setState({ timeIdx });
    });
  }

  componentWillReceiveProps(nextProps) {
    if (
      nextProps.params &&
      nextProps.params.timeIdx &&
      nextProps.params.timeIdx !== this.state.timeIdx
    ) {
      const timeIdx = Number(nextProps.params.timeIdx);
      if (Number.isInteger(timeIdx)) {
        this.setTimeIdx(timeIdx);
      } else {
        this.setTimeIdx(0);
      }
    }
  }

  componentWillUnmount() {
    removeTimeListener(this.callbackId);
  }

  setTimeIdx(timeIdx) {
    let pathname = this.props.location.pathname.split('/');
    let previousTime = -1;
    const search = this.props.location.search;

    this.setState({
      timeIdx,
    });
    updateTime(timeIdx);

    while (pathname.length > 3) {
      previousTime = Number(pathname.pop());
    }

    if (previousTime !== timeIdx) {
      pathname.push(timeIdx);
      pathname = pathname.join('/');
      this.props.history.push({
        pathname,
        search,
      });
    }
  }

  sliderTimeUpdate(event) {
    this.setTimeIdx(Number(event.target.value));
  }

  updateVCR(button) {
    let timeIdx = this.state.timeIdx;
    if (button.delta) {
      timeIdx += button.delta;
      timeIdx = timeIdx < 0 ? 0 : timeIdx;
      timeIdx =
        timeIdx >= this.props.dataset.data.time.length
          ? this.props.dataset.data.time.length - 1
          : timeIdx;
      this.setTimeIdx(timeIdx);
    } else if (button.action) {
      this[button.action]();
    }
  }

  play() {
    if (!this.playing) {
      this.playing = true;
      playTime();
    }
  }

  stop() {
    this.playing = false;
    stopTime();
    this.forceUpdate();
  }

  render() {
    return (
      <div
        className={[
          this.props.className,
          this.playing ? style.timePanelPlaying : style.timePanel,
        ].join(' ')}
      >
        <div className={style.linePiece}>
          <InlineToggleButton
            height="10px"
            options={VCR_CONTROL}
            defaultColor="white"
            activeColor="white"
            onChange={this.updateVCR}
          />
          <input
            className={style.timeSlider}
            type="range"
            min="0"
            max={this.props.dataset.data.time.length - 1}
            value={this.state.timeIdx}
            onChange={this.sliderTimeUpdate}
          />
        </div>
        <div className={style.linePiece}>
          <span className={style.progress}>
            {this.state.timeIdx + 1} / {this.props.dataset.data.time.length}
          </span>
          <span className={style.realTime}>
            {this.props.dataset.data.time.length
              ? this.props.dataset.data.time[this.state.timeIdx].value
              : ''}
          </span>
        </div>
      </div>
    );
  }
}

TimePanel.propTypes = {
  dataset: PropTypes.object,
  location: PropTypes.object,
  params: PropTypes.object,
  className: PropTypes.string,
  history: PropTypes.object.isRequired,
};

TimePanel.defaultProps = {
  dataset: undefined,
  location: undefined,
  params: undefined,
  className: '',
};
